package com.lute.controller;

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.security.oauth2.common.json.JSONException;
import org.springframework.security.oauth2.common.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lute.model.Approver;
import com.lute.model.ClientAccountingPeriodState;
import com.lute.model.ClientAdmin;
import com.lute.model.EmployeeAccountingPeriod;
import com.lute.model.EmployeeAccountingPeriodState;
import com.lute.model.User;
import com.lute.model.UserEntitlement;
import com.lute.utils.CreateMailForm;
import com.lute.utils.ServerErrorResponse;

@Controller
public class AccountingPeriodRejectServlet {
	
	@RequestMapping(value="/reject", method=RequestMethod.POST, headers="Content-type=application/json")
	public @ResponseBody String accountinPeriodRejected(@RequestBody String calendarJSON, HttpServletRequest request) throws JSONException {
		String result = "";
		String userIdStr;
		String from;
		String reason;
		JSONObject jsonReq;
		JSONObject jsonRes = new JSONObject();
		
		HttpSession session = request.getSession(false);
		if(session == null) {
			jsonRes.put("result", ServerErrorResponse.USER_NOT_LOGGED_IN.toString());
			result = jsonRes.toString();
			return result;
		}
		
		try {
			jsonReq = new JSONObject(calendarJSON);
			userIdStr = jsonReq.getString("userId");
			from = jsonReq.getString("from");
			reason = jsonReq.getString("reason");
		} catch(JSONException e) {
			jsonRes.put("result", ServerErrorResponse.MALFORMED_REQUEST.toString());
			result = jsonRes.toString();
			return result;
		}
		
		/* check if json data was not malformed */
		if( (jsonReq.isNull("userId")) && (jsonReq.isNull("from")) && (jsonReq.isNull("reason"))) {
			jsonRes.put("result",ServerErrorResponse.MALFORMED_REQUEST.toString());
			result = jsonRes.toString();
			return result;
		}
		
		String role = (String)session.getAttribute("role");
		
		/* check  authorization */
		if(!((role.equals("approver")) || (role.equals("clientAdmin")))) {
			jsonRes.put("result", ServerErrorResponse.USER_NOT_ENTITLED.toString());
			result = jsonRes.toString();
			System.out.println(result);
			return result;
		}
		
		if(reason.length() > 255) {
			jsonRes.put("result", ServerErrorResponse.REJECTION_REASON_TOO_LONG.toString());
			result = jsonRes.toString();
			System.out.println(result);
			return result;
		}
		
		int sessionUserId = (Integer)session.getAttribute("sessionUserId");
		int userId = Integer.parseInt(userIdStr);
		jsonRes.put("result", "");
		
		EmployeeAccountingPeriod employeeAccountingPeriod = null;
		
		try {
			
			employeeAccountingPeriod = UserEntitlement.checkUserPrivilegeToEmployeeAccountingPeriod(from,sessionUserId,userId,role,jsonRes);
			
			if(!(jsonRes.get("result").equals(""))) {
				result = jsonRes.toString();
				System.out.println(result);
				return result;
			}
			
			if(employeeAccountingPeriod == null) {
				jsonRes.put("result", ServerErrorResponse.UNKNOWN_ACCOUNTING_PERIOD.toString());
				result = jsonRes.toString();
				return result;
			}
			
			if((employeeAccountingPeriod.getClientAccountingPeriod().getClientAccountingPeriodState()
					.equals(ClientAccountingPeriodState.CLOSE.toString()))) {
				jsonRes.put("result", ServerErrorResponse.ACCOUNTING_PERIOD_ALREADY_CLOSED.toString());
				result = jsonRes.toString();
				return result;
			}
			
			String rejectedPerson;
			String rejectedPersonName="";
			
			if(role.equals("approver")) {
				if(employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.REJECTED_BY_APPROVER.toString())) {
					jsonRes.put("result", ServerErrorResponse.OPERATION_NOT_ALLOWED.toString());
					result = jsonRes.toString();
					System.out.println(result);
					return result;
				}
				if(sessionUserId == userId) {
					/* Approver want to reject his own calendar */
					jsonRes.put("result", ServerErrorResponse.OPERATION_NOT_ALLOWED.toString());
					result = jsonRes.toString();
					System.out.println(result);
					return result;
				} else {
					if(employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.SENT_TO_APPROVER.toString()) ||
					   employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.CHECKED_BY_APPROVER.toString())) {
						
						Approver approver = Approver.getApproverFromDB("id_user", sessionUserId);
						employeeAccountingPeriod.setCalendarApprover(approver.getId_user());
						rejectedPerson = approver.getFirst_name()+" "+approver.getLast_name();
						rejectedPersonName = approver.getFirst_name()+" "+approver.getLast_name();
						employeeAccountingPeriod.setEmployeeAccountingPeriodState(EmployeeAccountingPeriodState.REJECTED_BY_APPROVER.toString());
						employeeAccountingPeriod.setRejectedBy(rejectedPerson);
						employeeAccountingPeriod.setRejectedByUserRole(approver.getRole().getName());
						employeeAccountingPeriod.setRejectionDate(new GregorianCalendar());
						employeeAccountingPeriod.setRejectionReason(reason);
					} else {
						jsonRes.put("result", ServerErrorResponse.OPERATION_NOT_ALLOWED.toString());
						result = jsonRes.toString();
						System.out.println(result);
						return result;
					}
					
				}
			} else {
				if(employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.REJECTED_BY_CLIENT_ADMIN.toString())) {
					jsonRes.put("result", ServerErrorResponse.OPERATION_NOT_ALLOWED.toString());
					result = jsonRes.toString();
					System.out.println(result);
					return result;
				}
				if(employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.SENT_TO_CLIENT_ADMIN.toString()) ||
				   employeeAccountingPeriod.getEmployeeAccountingPeriodState().equals(EmployeeAccountingPeriodState.CHECKED_BY_CLIENT_ADMIN.toString())) {
					
					ClientAdmin clientAdmin = ClientAdmin.getClientAdminFromDB("id_user", sessionUserId);
					rejectedPerson = clientAdmin.getFirst_name()+" "+clientAdmin.getLast_name();
					rejectedPersonName = clientAdmin.getFirst_name()+" "+clientAdmin.getLast_name();
					employeeAccountingPeriod.setEmployeeAccountingPeriodState(EmployeeAccountingPeriodState.REJECTED_BY_CLIENT_ADMIN.toString());
					employeeAccountingPeriod.setRejectedBy(rejectedPerson);
					employeeAccountingPeriod.setRejectedByUserRole(clientAdmin.getRole().getName());
					employeeAccountingPeriod.setRejectionDate(new GregorianCalendar());
					employeeAccountingPeriod.setRejectionReason(reason);
				} else {
					jsonRes.put("result", ServerErrorResponse.OPERATION_NOT_ALLOWED.toString());
					result = jsonRes.toString();
					System.out.println(result);
					return result;
				}
			}
			
			/* update user's calendar in DataBase */
			EmployeeAccountingPeriod.updateEmployeeAccountingPeriodInDB(employeeAccountingPeriod);
			User user = User.getUserFromDB("id_user", userId);
			/* inform employee that his calendar was rejected via mail */
			CreateMailForm.prepareMailInCaseEmployeeAccPeriodRejected(user.getEmail(), rejectedPersonName);
			
		}catch(NullPointerException npe) {
			jsonRes.put("result", ServerErrorResponse.INTERNAL_ERROR.toString());
			result = jsonRes.toString();
			System.out.println(result);
			return result;
		}
		
		SimpleDateFormat rejectionDateFromater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		jsonRes.put("result","OK");
		jsonRes.put("newEmployeeAccountingPeriodState", employeeAccountingPeriod.getEmployeeAccountingPeriodState());
		jsonRes.put("rejectionReason",reason);
		jsonRes.put("rejectedBy", employeeAccountingPeriod.getRejectedBy());
		jsonRes.put("rejectionDate", rejectionDateFromater.format(employeeAccountingPeriod.getRejectionDate().getTime()));
		result = jsonRes.toString();
		return result;
	}
}
